package com.yc.framework.interceptor;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.yc.common.core.domain.AjaxResult;
import com.yc.common.core.domain.model.LoginUser;
import com.yc.system.service.IpLimitService;
import com.yc.common.utils.WebUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * IP限制拦截器 - 处理所有接口的访问频率限制
 */
@Component
public class IpLimitInterceptor implements HandlerInterceptor {

    private static final Logger log = LoggerFactory.getLogger(IpLimitInterceptor.class);

    @Autowired
    private IpLimitService ipLimitService;

    @Autowired
    private ObjectMapper objectMapper;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String uri = request.getRequestURI();
        String ipAddress = WebUtil.getIpAddr();
        boolean isLoginRequest = uri.contains("/login") || uri.contains("/register");

        // 记录请求信息以便日志分析
        log.debug("IP访问: {}, URI: {}, 登录请求: {}", ipAddress, uri, isLoginRequest);

        // 检查IP访问限制
        if (!ipLimitService.checkIpLimit(request, isLoginRequest)) {
            // 对于登录/注册请求，直接拒绝
            if (isLoginRequest) {
                log.warn("登录/注册请求频率过高 - IP: {}", ipAddress);
                responseError(response, "访问过于频繁，请稍后再试");
                return false;
            }

            // 对于其他请求，检查用户是否已登录
            Authentication authentication = WebUtil.getAuthentication();
            if (authentication != null && authentication.getPrincipal() instanceof LoginUser) {
                LoginUser loginUser = (LoginUser) authentication.getPrincipal();
                Long userId = loginUser.getUser().getId();

                // 记录访问并检查用户是否被禁用
                ipLimitService.recordAccess(request, userId, uri);

                // 如果用户违规次数达到阈值，则禁用用户账号
                if (ipLimitService.shouldBanUser(userId)) {
                    // 禁用用户 - 将用户状态设置为停用(status=1)
                    ipLimitService.banUser(userId);
                    log.warn("用户被禁用 - 用户ID: {}, IP: {}", userId, ipAddress);
                    responseError(response, "您的账号因频繁访问已被临时禁用");
                    return false;
                }

                // 检查用户是否已被禁用
                if (ipLimitService.isUserBanned(userId)) {
                    log.warn("已禁用用户尝试访问 - 用户ID: {}, IP: {}", userId, ipAddress);
                    responseError(response, "您的账号因频繁访问已被临时禁用");
                    return false;
                }
            }

            // 记录违规IP，连续违规会被封禁
            ipLimitService.recordIpViolation(ipAddress);

            // 未登录用户或未被禁用的用户，返回访问频率过高的提示
            log.warn("访问频率过高 - IP: {}, URI: {}", ipAddress, uri);
            responseError(response, "访问频率过高，请稍后再试");
            return false;
        }

        // 记录正常访问
        Authentication authentication = WebUtil.getAuthentication();
        if (authentication != null && authentication.getPrincipal() instanceof LoginUser) {
            LoginUser loginUser = (LoginUser) authentication.getPrincipal();
            ipLimitService.recordAccess(request, loginUser.getUser().getId(), uri);
        } else {
            ipLimitService.recordAccess(request, null, uri);
        }

        return true;
    }

    private void responseError(HttpServletResponse response, String message) throws IOException {
        response.setContentType("application/json;charset=UTF-8");
        response.setStatus(429); // 直接使用数字状态码 429 表示 Too Many Requests

        try (PrintWriter writer = response.getWriter()) {
            writer.write(objectMapper.writeValueAsString(AjaxResult.error(429, message)));
        }
    }
}